// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace SnapObjects.Data
{
    /// <summary>
    ///     Represents an object that can track data for the detail model after the ISqlModelMapper.TrackMaster method is called.
    ///     It is used when working with the master-detail models where the ModelEmbedded attribute is applied in a property of the master model.
    /// </summary>
    /// <typeparam name="TModel">The type of a model class.</typeparam>
    public interface IDetailTracker<TModel>
    {
        /// <summary>
        ///     Gets a reference to the master model object.
        /// </summary>
        TModel MasterModel { get; }

        //IModelEntry MasterEntry { get; }

        /// <summary>
        ///     Tracks an insert, update or delete operation on the table which the detail model is mapped to, 
        ///     when working with the master-detail models (where the ModelEmbedded attribute is applied in a 
        ///     property of the master model). The data state determines which type of operation to be performed. 
        ///     The data to be manipulated is cached in a TDetailModel object.When ISqlModelMapper.SaveChanges
        ///     method is called, a SQL statement (INSERT, UPDATE, or DELETE) will be first generated using the 
        ///     data cached in the TDetailModel object and the mapping information defined in TDetailModel, 
        ///     and then executed.
        /// </summary>
        /// <typeparam name="TDetailModel">The type of the detail model class.</typeparam>
        /// <param name="propertyExpr">
        ///     A property of the master model (TModel) where the ModelEmbedded attribute is applied.
        ///     The type of this property is TDetailModel.
        ///     This property is specified by an expression.
        /// </param>
        /// <param name="modelEntry">
        ///     An <see cref="IModelEntry{TDetailModel}"/> object which contains the data and data state and which will be tracked.
        /// </param>
        /// <returns>Returns the current <see cref="IDetailTracker{TModel}"/> object.</returns>
        IDetailTracker<TModel> TrackDetail<TDetailModel>(
            Expression<Func<TModel, object>> propertyExpr,
            IModelEntry<TDetailModel> modelEntry);

        /// <summary>
        /// Tracks one or more insert, update or delete operations on the table which the detail model 
        /// is mapped to, when working with the master-detail models (where the ModelEmbedded attribute 
        /// is applied in a property of the master model). The data state determines which type of operation 
        /// to be performed. The data to be manipulated is cached in a sequence of TDetailModel objects.
        /// When ISqlModelMapper.SaveChanges is called, one or more SQL statements (INSERT, UPDATE, or DELETE) 
        /// will be first generated using the data cached in TDetailModel objects and the mapping information 
        /// defined in TDetailModel, and then executed.
        /// </summary>
        /// <typeparam name="TDetailModel">The type of the detail model class.</typeparam>
        /// <param name="propertyExpr">
        ///     A property of the master model (TModel) where the ModelEmbedded attribute is applied.
        ///     The type of this property is a collection of TDetailModel.
        ///     This property is specified by an expression.
        /// </param>
        /// <param name="modelEntry">An <see cref="IEnumerable{IModelEntry}>"/> object that contains the data and data state which will be tracked.</param>
        /// <returns>Returns the current <see cref="IDetailTracker{TModel}"/> object.</returns>
        IDetailTracker<TModel> TrackDetails<TDetailModel>(
            Expression<Func<TModel, object>> propertyExpr,
            IEnumerable<IModelEntry<TDetailModel>> modelEntry);

        /// <summary>
        ///     Tracks an insert, update or delete operation on the table which the granddetail model is
        ///     mapped to when working with the master-detail-granddetail models where the ModelEmbedded 
        ///     attribute is applied in a property of the master model and a property of the detail model. 
        ///     The data state determines which type of operation to be performed. The data to be manipulated 
        ///     is cached in a TGrandDetailModel object.When ISqlModelMapper.SaveChanges is called, a SQL 
        ///     statement (INSERT, UPDATE, or DELETE) will be generated using the data cached in the 
        ///     TGrandDetailModel object and the mapping information defined in TGrandDetailModel, 
        ///     and then the SQL statement will be executed.
        /// </summary>
        /// <typeparam name="TDetailModel">The type of the detail model class.</typeparam>
        /// <typeparam name="TGrandDetailModel">The type of the granddetail model class.</typeparam>
        /// <param name="propertyExpr">
        ///     A property of the master model (TModel) where the ModelEmbedded attribute is applied.
        ///     The type of this property is TDetailModel.
        ///     This property is specified by an expression.
        /// </param>
        /// <param name="detailPropertyExpr">
        ///     A property of the detail model where the ModelEmbedded attribute is applied.
        ///     The type of this property is TGrandDetailModel.
        ///     This property is specified by an expression.
        /// </param>
        /// <param name="grandModelEntry">
        ///     An <see cref="IModelEntry{TGrandDetailModel}"/> object that contains the data and data state and which will be tracked. 
        ///     The data corresponds to the property specified by detailPropertyExpr.
        /// </param>
        /// <returns>Returns the current <see cref="IDetailTracker{TModel}"/> object.</returns>
        IDetailTracker<TModel> TrackGrandDetail<TDetailModel, TGrandDetailModel>(
            Expression<Func<TModel, object>> propertyExpr,
            Expression<Func<TDetailModel, object>> detailPropertyExpr,
            IModelEntry<TGrandDetailModel> grandModelEntry);

        /// <summary>
        ///     Tracks an insert, update or delete operation on the table which the granddetail model is mapped to 
        ///     when working with the master-detail-granddetail models where the ModelEmbedded attribute is applied 
        ///     in a property of the master model and a property of the detail model. The data state determines which
        ///     type of operation to be performed. The data to be manipulated is cached in a sequence of TGrandDetailModel 
        ///     objects.When ISqlModelMapper.SaveChanges is called, a SQL statement (INSERT, UPDATE, or DELETE) will 
        ///     be generated using the data cached in TGrandDetailModel and the mapping information defined in 
        ///     TGrandDetailModel, and then the SQL statement will be executed.
        /// </summary>
        /// <typeparam name="TDetailModel">The type of the detail model class.</typeparam>
        /// <typeparam name="TGrandDetailModel">The type of the granddetail model class.</typeparam>
        /// <param name="propertyExpr">
        ///     A property of the master model where the ModelEmbedded attribute is applied.
        ///     The type of this property is TDetailModel.
        ///     This property is specified by an expression.
        /// </param>
        /// <param name="detailPropertyExpr">
        ///     A property of the detail model where the ModelEmbedded attribute is applied.
        ///     The type of this property is a collection of TGrandDetailModel.
        ///     This property is specified by an expression.
        /// </param>
        /// <param name="grandModelEntries">
        ///     An <see cref="IEnumerable{IModelEntry}"/> object which contains the data and data state and 
        ///     which will be tracked. The data corresponds to the second property expression.
        /// </param>
        /// <returns>Returns the current <see cref="IDetailTracker{TModel}"/> object.</returns>
        IDetailTracker<TModel> TrackGrandDetails<TDetailModel, TGrandDetailModel>(
            Expression<Func<TModel, object>> propertyExpr,
            Expression<Func<TDetailModel, object>> detailPropertyExpr,
            IEnumerable<IModelEntry<TGrandDetailModel>> grandModelEntries);

        /*IDetailTracker<TModel> TrackDetailAndGrandDetail<TDetailModel, TGrandDetailModel>(
            Expression<Func<TModel, object>> propertyExpr,
            IModelEntry<TDetailModel> modelEntry,
            Expression<Func<TDetailModel, object>> detailPropertyExpr,
            IModelEntry<TGrandDetailModel> grandModelEntry);

        IDetailTracker<TModel> TrackDetailAndGrandDetails<TDetailModel, TGrandDetailModel>(
            Expression<Func<TModel, object>> propertyExpr,
            IModelEntry<TDetailModel> modelEntry,
            Expression<Func<TDetailModel, object>> detailPropertyExpr,
            IEnumerable<IModelEntry<TGrandDetailModel>> grandModelEntries);*/

        /// <summary>
        ///     Updates the database by executing the data changes tracked by the ISqlModelMapper object.
        /// </summary>
        /// <returns>
        ///     Returns an IDbResult object which can be used to conveniently get the result of the executed database operation.
        /// </returns>
        IDbResult SaveChanges();
    }
}
